#include "global_config.h"
#include "eeprom_driver.h"

/* Global configuration instance */
system_config_complete_t g_system_config;

/* Default configuration */
static const system_config_complete_t default_config = {
    .system = {
        .version = 0x0100,
        .magic = 0xAA55AA55,
        .crc32 = 0
    },
    .io = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 100,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 100
        },
        .inputs = {
            [0 ... 11] = {
                .enabled = RT_TRUE,
                .normally_open = RT_FALSE,
                .filter_time = 100,
                .current_state = RT_FALSE,
                .valid_state = RT_FALSE,
                .debounce_count = 0,
                .debounce_threshold = 5
            }
        },
        .outputs = {
            [0 ... 11] = {
                .normally_open = RT_FALSE,
                .command_state = RT_FALSE,
                .current_state = RT_FALSE,
                .safe_state = RT_FALSE,
                .on_delay = 0,
                .off_delay = 0
            }
        }
    },
    .adc = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 100,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 100
        },
        .channels = {
            [0 ... 3] = {
                .enabled = RT_TRUE,
                .min_current = 4.0f,
                .max_current = 20.0f,
                .min_engineering = 0.0f,
                .max_engineering = 100.0f,
                .current_value = 0.0f,
                .engineering_value = 0.0f,
                .adc_raw = 0,
                .filter_count = 0
            }
        }
    },
    .temp = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 1000,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 1000
        },
        .channels = {
            [0] = {.enabled = RT_TRUE, .type = SENSOR_PT100, .cal_table_size = 4},
            [1] = {.enabled = RT_TRUE, .type = SENSOR_PT100, .cal_table_size = 4},
            [2] = {.enabled = RT_TRUE, .type = SENSOR_NTC10K, .cal_table_size = 4},
            [3] = {.enabled = RT_TRUE, .type = SENSOR_NTC10K, .cal_table_size = 4}
        }
    },
    .flow = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 500,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 500
        },
        .channels = {
            [0 ... 1] = {
                .enabled = RT_TRUE,
                .pulse_constant = 1000.0f,
                .k_factor = 1.0f
            }
        }
    },
    .water = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 1000,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 1000
        },
        .channels = {
            [0 ... 1] = {
                .enabled = RT_TRUE,
                .cal_table_size = 4
            }
        }
    },
    .valve = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 0,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 10
        },
        .enabled = RT_TRUE,
        .max_steps = 1000,
        .current_step = 0,
        .step_delay = 10,
        .step_sequence = {0x01, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x09},
        .current_phase = 0,
        .position_percent = 0.0f,
        .moving = RT_FALSE,
        .target_step = 0
    },
    .pid = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 0,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 1000
        },
        .controllers = {
            [0] = {
                .enabled = RT_TRUE,
                .auto_mode = RT_FALSE,
                .kp = 2.0f,
                .ki = 0.1f,
                .kd = 1.0f,
                .setpoint = 25.0f,
                .output_min = 0.0f,
                .output_max = 100.0f,
                .control_interval = 1000
            },
            [1] = {
                .enabled = RT_TRUE,
                .auto_mode = RT_FALSE,
                .kp = 2.0f,
                .ki = 0.1f,
                .kd = 1.0f,
                .setpoint = 25.0f,
                .output_min = 0.0f,
                .output_max = 100.0f,
                .control_interval = 1000
            }
        }
    },
    .alarm = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 0,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 100
        },
        .alarms = {
            [0 ... 9] = {
                .enabled = RT_FALSE,
                .low_limit = 0.0f,
                .high_limit = 100.0f,
                .deadband = 1.0f,
                .level = ALARM_LEVEL_WARNING
            }
        }
    },
    .log = {
        .base = {
            .enabled = RT_TRUE,
            .filter_time = 0,
            .k_factor = 1.0f,
            .b_offset = 0.0f,
            .update_interval = 1000
        },
        .max_entries = 1000,
        .current_index = 0,
        .wrap_around = 0,
        .enable_console = RT_TRUE,
        .enable_storage = RT_TRUE,
        .storage_interval = 60000
    }
};

/* Initialize calibration tables with default values */
static void init_calibration_tables(void)
{
    /* Temperature calibration tables */
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            g_system_config.temp.channels[i].cal_table[j].measured = j * 10.0f;
            g_system_config.temp.channels[i].cal_table[j].standard = j * 10.0f;
        }
    }
    
    /* Water quality calibration tables */
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 4; j++) {
            g_system_config.water.channels[i].cal_table[j].measured = j * 1000.0f;
            g_system_config.water.channels[i].cal_table[j].standard = j * 1.0f;
        }
    }
}

rt_err_t config_init(void)
{
    rt_err_t result;
    
    /* Copy default configuration */
    rt_memcpy(&g_system_config, &default_config, sizeof(system_config_complete_t));
    
    /* Initialize calibration tables */
    init_calibration_tables();
    
    /* Try to load configuration from EEPROM */
    result = config_load();
    if (result != RT_OK) {
        LOG_W("Failed to load config from EEPROM, using defaults\n");
        
        /* Calculate CRC for default config */
        g_system_config.system.crc32 = config_calculate_crc(&g_system_config);
        
        /* Save default config to EEPROM */
        result = config_save();
        if (result != RT_OK) {
            LOG_E("Failed to save default config to EEPROM\n");
        }
    }
    
    LOG_I("Configuration initialized successfully\n");
    return RT_OK;
}

rt_err_t config_load(void)
{
    system_config_complete_t loaded_config;
    rt_err_t result;
    
    /* Load configuration from EEPROM */
    result = eeprom_load_config(&loaded_config, sizeof(loaded_config));
    if (result != RT_OK) {
        LOG_E("Failed to load config from EEPROM\n");
        return result;
    }
    
    /* Validate configuration */
    result = config_validate(&loaded_config);
    if (result != RT_OK) {
        LOG_E("Loaded config validation failed\n");
        return result;
    }
    
    /* Copy loaded configuration */
    rt_memcpy(&g_system_config, &loaded_config, sizeof(system_config_complete_t));
    
    LOG_I("Configuration loaded successfully from EEPROM\n");
    return RT_OK;
}

rt_err_t config_save(void)
{
    rt_err_t result;
    
    /* Update CRC before saving */
    g_system_config.system.crc32 = config_calculate_crc(&g_system_config);
    
    /* Save configuration to EEPROM */
    result = eeprom_save_config(&g_system_config, sizeof(g_system_config));
    if (result != RT_OK) {
        LOG_E("Failed to save config to EEPROM\n");
        return result;
    }
    
    LOG_I("Configuration saved successfully to EEPROM\n");
    return RT_OK;
}

rt_err_t config_validate(system_config_complete_t *config)
{
    if (config == RT_NULL) {
        return RT_ERR_PARAM;
    }
    
    /* Check magic number */
    if (config->system.magic != 0xAA55AA55) {
        LOG_E("Config magic number invalid: 0x%08X\n", config->system.magic);
        return RT_ERR_CHECKSUM;
    }
    
    /* Check CRC */
    uint32_t calculated_crc = config_calculate_crc(config);
    if (calculated_crc != config->system.crc32) {
        LOG_E("Config CRC mismatch: calc=0x%08X, stored=0x%08X\n", 
              calculated_crc, config->system.crc32);
        return RT_ERR_CHECKSUM;
    }
    
    /* Validate parameter ranges */
    for (int i = 0; i < 12; i++) {
        if (config->io.inputs[i].filter_time > 10000) {
            config->io.inputs[i].filter_time = 100;
        }
    }
    
    for (int i = 0; i < 4; i++) {
        if (config->temp.channels[i].cal_table_size > 4) {
            config->temp.channels[i].cal_table_size = 4;
        }
    }
    
    return RT_OK;
}

uint32_t config_calculate_crc(system_config_complete_t *config)
{
    /* Simple CRC calculation - replace with proper algorithm if needed */
    uint32_t crc = 0;
    uint8_t *data = (uint8_t*)config;
    uint32_t data_size = sizeof(system_config_complete_t) - sizeof(config->system.crc32);
    
    for (uint32_t i = 0; i < data_size; i++) {
        crc += data[i];
    }
    
    return crc;
}